import http from "http";
/**
 * @typedef {http.IncomingMessage} Request
 * @typedef {http.ServerResponse} Response
 * @typedef {(req: Request, res: Response) => void | Promise<void>} Middleware
 */

class Server {
  /** @type {*} */
  instance;
  /** @type {{ method: "*" | "GET" | "POST", path: string, handler: Middleware }[]} */
  routes = [];

  /**
   * @param {string | Middleware} arg1
   * @param {Middleware?} arg2
   */
  use(arg1, arg2) {
    let path, handler;
    if (typeof arg1 === "string") {
      path = arg1;
      handler = arg2;
    } else {
      path = "*";
      handler = arg1;
    }
    this.routes.push({ method: "*", path, handler });
    return this;
  }
  /**
   * @param {string} path
   * @param {Middleware} handler
   */
  get(path, handler) {
    this.routes.push({ method: "GET", path, handler });
    return this;
  }
  /**
   * @param {string} path
   * @param {Middleware} handler
   */
  post(path, handler) {
    this.routes.push({ method: "POST", path, handler });
    return this;
  }
  /**
   * @param {string} path
   * @param {Middleware} handler
   */
  put(path, handler) {
    this.routes.push({ method: "PUT", path, handler });
    return this;
  }

  /**
   * @param {number} port
   */
  listen(port) {
    this.instance = http
      .createServer(async (req, res) => {
        const { method: _method, url } = req;
        const len = this.routes.length;
        for (let i = 0; i < len; i++) {
          const { method, path, handler } = this.routes[i];
          if (
            (path === "*" || url.startsWith(path)) &&
            (method === "*" || method === _method)
          ) {
            await handler(req, res);
          }
          if (res.headersSent || res.body) {
            console.log(_method + (method === "*" ? "*" : ""), url);
            break;
          }
        }
        if ((res.headersSent && res.writable) || res.body) {
          if (res.body && typeof res.body === "object") {
            res.setHeader("content-type", "application/json");
            res.body = JSON.stringify(res.body);
          }
          return res.end(res.body);
        }
        res.writeHead(404, {
          "content-type": "text/plain",
        });
        res.end("endpoint notfound");
      })
      .on("error", (error) => {
        console.log("!!ERROR!!");
        console.log(error);
      })
      .listen(port);
  }
}

const server = new Server();
server
  .use((req, res) => {
    res.setHeader("access-control-allow-origin", "*");
  })
  .use((req) => {
    return new Promise((resolve, reject) => {
      let data = [];
      const contentType = req.headers["content-type"];
      req.on("data", (chunk) => {
        data = [...data, ...chunk];
      });
      req.on("end", () => {
        if (/json/.test(contentType)) {
          req.body = JSON.parse(Buffer.from(data).toString("utf8"));
        }
        resolve();
      });
      req.on("error", reject);
    });
  })
  .get("/llm/np/years", (req, res) => {
    const max = random(10, 30);
    const start = random(1000, 1900);
    const body = [];
    for (let i = 1; i < max; i++) {
      body.push({
        age: `${i}岁`,
        gy_year: `${start + i}年`,
        ls_year: "道光XXX年XX",
        raw: `${start + i}年（道光XXX年XX）${i}岁`,
      });
    }
    res.body = body;
  })
  .post("/llm/np/query", async (req, res) => {
    await sleep(1000);
    const max = random(10, 20);
    for (let i = 0; i < max; i++) {
      res.write(
        JSON.stringify({
          event_time: "xxxx年",
          event_person: randomPersons(),
          event_place: [],
          event_org: [],
          event_title: "XXX",
          event_content: "xxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxxx, xxxxx, xxxxxxx.",
          event_type: randomEvent(),
        }),
      );
      res.write("\n");
      // await sleep(50);
    }
  })
  .listen(8888);

async function sleep(duration) {
  return new Promise((resolve) => {
    setTimeout(resolve, duration);
  });
}

function randomPersons() {
  const persons = ["AAA", "BBB", "CCC", "DDD"];
  return [
    ...new Set(
      Array(random(0, persons.length))
        .fill(undefined)
        .map(() => persons[random(0, persons.length - 1)]),
    ),
  ];
}

function randomEvent() {
  const events = [
    "政治活动",
    "经济与实业",
    "教育与文化",
    "外交事务",
    "社会公益与慈善",
    "家庭与个人生活",
    "信件往来",
    "思想与著录",
    "其他",
  ];
  return events[random(0, events.length - 1)];
}

function random(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1));
}
